/** * QuickUML; A simple UML tool that demonstrates one use of the Java Diagram Package Copyright (C) 2001 Eric Crahen <crahen@cse.buffalo.edu> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package uml.ui; import java.awt.Component; import java.awt.Dimension; import java.awt.Event; import java.awt.Frame; import java.awt.event.ActionEvent; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFileChooser; import javax.swing.JMenu; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.KeyStroke; import uml.diagram.AssociationLink; import uml.diagram.AssociationLinkEditor; import uml.diagram.AssociationLinkRenderer; import uml.diagram.ClassEditor; import uml.diagram.ClassFigure; import uml.diagram.ClassRenderer; import uml.diagram.CompositionLink; import uml.diagram.CompositionLinkEditor; import uml.diagram.CompositionLinkRenderer; import uml.diagram.DependencyLink; import uml.diagram.DependencyLinkEditor; import uml.diagram.DependencyLinkRenderer; import uml.diagram.GeneralizationLink; import uml.diagram.GeneralizationLinkEditor; import uml.diagram.GeneralizationLinkRenderer; import uml.diagram.InterfaceEditor; import uml.diagram.InterfaceFigure; import uml.diagram.InterfaceRenderer; import uml.diagram.NoteEditor; import uml.diagram.NoteFigure; import uml.diagram.NoteRenderer; import uml.diagram.RealizationLink; import uml.diagram.RealizationLinkEditor; import uml.diagram.RealizationLinkRenderer; import diagram.Diagram; import diagram.DiagramModel; /** * @class DiagramContainer * * @date 08-20-2001 * @author Eric Crahen * @version 1.0 */ public class DiagramContainer extends JScrollPane { protected Action saveAction = new SaveAction(); protected Action closeAction = new CloseAction(); protected Action printAction = new PrintAction(); protected Action scaledPrintAction = new ScaledPrintAction(); protected Action exportAction = new ExportGIFAction(); protected Action resizeAction = new ResizeAction(); // Placeholders for the menu, the real actions are install on the diagram // when ever one is place in the container by the diagram ui protected Action copyAction = new CopyAction(); protected Action cutAction = new CutAction(); protected Action pasteAction = new PasteAction(); protected Dimension defaultSize; // Color editor data private final static String[] colorProperties = { "composition.foreground","composition.background", "class.foreground","class.background", "association.foreground","association.background", "dependency.foreground","dependency.background", "diagram.foreground","diagram.background", "generalization.foreground","generalization.background", "interface.foreground","interface.background", "note.foreground","note.background", "realization.foreground","realization.background" }; // Font editor data private final static String[] fontProperties = { "composition.font", "class.font", "association.font", "diagram.font", "generalization.font", "interface.font", "note.font", "dependency.font", "realization.font" }; /** * Create a new Container for a diagram */ public DiagramContainer() { super(VERTICAL_SCROLLBAR_ALWAYS, HORIZONTAL_SCROLLBAR_ALWAYS); setView( createDiagram() ); } /** * Update the menu bar. Add toggle option, etc. * * @param FlatMenuBar */ public void updateMenus(FlatMenuBar menuBar) { JMenu menu = menuBar.getMenu("File"); menu.add(new NewAction()); menu.add(new OpenAction()); menu.add(closeAction); menu.add(saveAction); menu.addSeparator(); menu.add(exportAction); menu.addSeparator(); menu.add(printAction); menu.add(scaledPrintAction); menu = menuBar.getMenu("Edit"); menu.add(copyAction); menu.add(cutAction); menu.add(pasteAction); menu = menuBar.getMenu("Options"); menu.add(resizeAction); menu.add(new FontAction(this, fontProperties)); menu.add(new ColorAction(this, colorProperties)); menu.add(new JSeparator(), -1); JCheckBoxMenuItem item = new JCheckBoxMenuItem(new ToggleRefreshAction()); item.setState(true); menu.add(item, -1); menu = menuBar.getMenu("Tool"); menu.add(new BuildAction(this)); } /** * Create a new diagram */ public Diagram createDiagram() { Diagram diagram = new Diagram(); // Install Link renderers diagram.setFigureRenderer(CompositionLink.class, new CompositionLinkRenderer()); diagram.setFigureRenderer(AssociationLink.class, new AssociationLinkRenderer()); diagram.setFigureRenderer(GeneralizationLink.class, new GeneralizationLinkRenderer()); diagram.setFigureRenderer(RealizationLink.class, new RealizationLinkRenderer()); diagram.setFigureRenderer(DependencyLink.class, new DependencyLinkRenderer()); // Install Figure renderers diagram.setFigureRenderer(ClassFigure.class, new ClassRenderer()); diagram.setFigureRenderer(InterfaceFigure.class, new InterfaceRenderer()); diagram.setFigureRenderer(NoteFigure.class, new NoteRenderer()); // Install Figure editors diagram.setFigureEditor(NoteFigure.class, new NoteEditor()); diagram.setFigureEditor(ClassFigure.class, new ClassEditor()); diagram.setFigureEditor(InterfaceFigure.class, new InterfaceEditor()); // Install Link editors diagram.setFigureEditor(CompositionLink.class, new CompositionLinkEditor()); diagram.setFigureEditor(GeneralizationLink.class, new GeneralizationLinkEditor()); diagram.setFigureEditor(RealizationLink.class, new RealizationLinkEditor()); diagram.setFigureEditor(DependencyLink.class, new DependencyLinkEditor()); diagram.setFigureEditor(AssociationLink.class, new AssociationLinkEditor()); if(defaultSize != null) resizeDiagram(diagram, defaultSize); return diagram; } /** * Get the diagram for this view. * * @return Diagram */ public Diagram getView() { return (Diagram)getViewport().getView(); } /** * Set the diagram for this view. * * @param Diagram */ public void setView(Diagram diagram) { Diagram oldDiagram = getView(); setViewportView(diagram); if(diagram == null) { // Disable actions that need a diagram closeAction.setEnabled(false); saveAction.setEnabled(false); exportAction.setEnabled(false); printAction.setEnabled(false); scaledPrintAction.setEnabled(false); resizeAction.setEnabled(false); copyAction.setEnabled(false); cutAction.setEnabled(false); pasteAction.setEnabled(false); } else if(oldDiagram == null) { // Enable actions that need a diagram closeAction.setEnabled(true); saveAction.setEnabled(true); exportAction.setEnabled(true); printAction.setEnabled(true); scaledPrintAction.setEnabled(true); resizeAction.setEnabled(true); copyAction.setEnabled(true); cutAction.setEnabled(true); pasteAction.setEnabled(true); } super.firePropertyChange("diagram.container", oldDiagram, diagram); } /** * Find the Frame for this event */ protected Component getFrame(ActionEvent e) { return getFrame((Component)e.getSource()); } protected Frame getFrame(Component frame) { for(;!(frame instanceof Frame); frame = frame.getParent()) if(frame instanceof JPopupMenu) frame = ((JPopupMenu)frame).getInvoker(); return (frame instanceof Frame) ? (Frame)frame : null; } public Frame getFrame() { return getFrame(this); } /** * Load an Icon with the IconManager */ protected Icon getIcon(String name) { return IconManager.getInstance().getIconResource(this, name); } /** * Popup an error message */ protected void displayError(Throwable t) { t.printStackTrace(); displayError(t.getClass().getName(), t.getMessage()); } /** * Popup an error message */ protected void displayError(String title, String msg) { JOptionPane.showMessageDialog(this, msg, title, JOptionPane.ERROR_MESSAGE); } /** * Resize & update the diagram */ protected void resizeDiagram(Diagram diagram, Dimension d) { diagram.setMinimumSize(d); diagram.setPreferredSize(d); diagram.setBounds(0, 0, d.width, d.height); doLayout(); } /** * @class NewAction * */ protected class NewAction extends AbstractAction { public NewAction() { super("New", getIcon("images/New.gif")); } public void actionPerformed(ActionEvent e) { setView( createDiagram() ); } } /** * @class CloseAction * */ protected class CloseAction extends AbstractAction { public CloseAction() { super("Close", getIcon("images/Close.gif")); } public void actionPerformed(ActionEvent e) { setView( null ); } } /** * @class OpenAction * */ protected class OpenAction extends FileAction { private SimpleFilter filter = new SimpleFilter("dia", "Diagrams"); public OpenAction() { super("Open", getIcon("images/Open.gif")); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('O', Event.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { // Configure the chooser for the open request JFileChooser chooser = getChooser(); chooser.setAcceptAllFileFilterUsed(false); chooser.setFileFilter(filter); if(JFileChooser.APPROVE_OPTION == chooser.showOpenDialog(getFrame(e))) openFile(chooser.getSelectedFile()); } public void openFile(File file) { try { // Check that the file name matches String name = file.getName().toLowerCase(); if(!name.endsWith(".dia")) throw new RuntimeException("Not a valid diagram file extension"); ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file)); // Get the current view or create one Diagram diagram = getView(); if(diagram == null) setView(diagram = createDiagram()); diagram.setModel((DiagramModel)ois.readObject()); diagram.repaint(); } catch(Throwable t) { t.printStackTrace(); displayError("File Error", "Invalid diagram file"); } } } /* OpenAction */ /** * @class SaveAction * */ protected class SaveAction extends FileAction { private SimpleFilter filter = new SimpleFilter("dia", "Diagrams"); public SaveAction() { super("Save", getIcon("images/Save.gif")); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('S', Event.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { // Configure the chooser for the save request JFileChooser chooser = getChooser(); chooser.setAcceptAllFileFilterUsed(false); chooser.setFileFilter(filter); if(JFileChooser.APPROVE_OPTION == chooser.showSaveDialog(getFrame(e))) saveFile(chooser.getSelectedFile()); } public void saveFile(File file) { // Adjust the file name to match String name = file.getName().toLowerCase(); if(!name.endsWith(".dia")) file = new File(file.getName() + ".dia"); try { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file)); oos.writeObject((DiagramModel)getView().getModel()); } catch(Throwable t) { t.printStackTrace(); displayError("File Error", "Error writing to file"); } } } /* SaveAction */ /** * @class ExportAction * */ protected class ExportGIFAction extends ExportAction { private SimpleFilter filter = new SimpleFilter("gif", "Images"); public ExportGIFAction() { super("Save Image", getIcon("images/ExportImage.gif")); } protected Component getComponent() { return getView(); } public void actionPerformed(ActionEvent e) { // Configure the chooser for the save request JFileChooser chooser = getChooser(); chooser.setAcceptAllFileFilterUsed(false); chooser.setFileFilter(filter); if(JFileChooser.APPROVE_OPTION == chooser.showSaveDialog(getFrame(e))) { try { writeGIF(chooser.getSelectedFile()); } catch(Throwable t) { displayError(t); } } } } /** * @class PrintAction * */ protected class PrintAction extends PrintableAction { public PrintAction() { super("Print ..."); } public Component getComponent() { return getView(); } } /** * @class ScaledPrintAction * */ protected class ScaledPrintAction extends ScaledPrintableAction { public ScaledPrintAction() { super("Scaled Print", getIcon("images/Print.gif")); } public Component getComponent() { return getView(); } } /** * @class CopyAction * */ protected class CopyAction extends AbstractAction { public CopyAction() { super("Copy", getIcon("images/Copy.gif")); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('C', Event.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { Diagram diagram = getView(); if(diagram != null) { Action action = diagram.getActionMap().get("copy"); if(action != null) action.actionPerformed(e); } } } /** * @class CutAction * */ protected class CutAction extends AbstractAction { public CutAction() { super("Cut", getIcon("images/Cut.gif")); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('X', Event.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { Diagram diagram = getView(); if(diagram != null) { Action action = diagram.getActionMap().get("cut"); if(action != null) action.actionPerformed(e); } } } /** * @class PasteAction * */ protected class PasteAction extends AbstractAction { public PasteAction() { super("Paste", getIcon("images/Paste.gif")); putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke('V', Event.CTRL_MASK)); } public void actionPerformed(ActionEvent e) { Diagram diagram = getView(); if(diagram != null) { Action action = diagram.getActionMap().get("paste"); if(action != null) action.actionPerformed(e); } } } /** * @class ResizeAction * */ protected class ResizeAction extends AbstractAction { public ResizeAction() { super("Resize ..."); } public void actionPerformed(ActionEvent e) { Diagram diagram = getView(); if(diagram != null) promptResize(diagram); } protected void promptResize(Diagram diagram) { SizePanel size = new SizePanel(diagram); int n = JOptionPane.showConfirmDialog(DiagramContainer.this, size, "Resize Diagram", JOptionPane.OK_CANCEL_OPTION); if(n == JOptionPane.OK_OPTION) { defaultSize = size.getDimension(defaultSize); resizeDiagram(diagram, defaultSize); } } } /** * @class ToggleRefreshAction * */ protected class ToggleRefreshAction extends AbstractAction { public ToggleRefreshAction() { super("Fast refresh"); } public void actionPerformed(ActionEvent e) { Diagram diagram = getView(); if(diagram != null) { boolean toggle = !diagram.isFastRefreshEnabled(); diagram.enableFastRefresh(toggle); } } } }